<script setup lang="ts">
import { type PropType, ref } from "vue";
import type { ToolInstallState } from "@/pages/tools/common/types";
import { hc } from "@/framework/vue/util/render";
import { DownloadOutlined, LoadingOutlined } from "@ant-design/icons-vue";
import path from "path-browserify-esm";
import { existsFile } from "@/framework/util/fs";
import { message } from "ant-design-vue";
import { downloadAndUnzip, installArchiveFile } from "@/pages/tools/common/util";
import type { UnzipCompleteArgs } from "@common/archives-file-types";

/* 压缩包安装 */
defineOptions({ name: "archive-install-operation" });
const props = defineProps({
  // ID标识
  id: { type: String, required: true },
  // 是否已安装
  isInstalled: { type: Boolean, default: false },
  // 下载连接
  downloadUrl: { type: String, required: true },
  // 下载文件本地保存路径(压缩包文件的绝对路径)
  savePath: { type: String, required: true },
  // 解压完成回调的第二个参数
  completeArgs: { type: [Object, Array, Number, Boolean, String, BigInt] as PropType<any> },
  // 解押完成回调
  afterUnzipComplete: { type: Function as PropType<(e: UnzipCompleteArgs, args?: any) => void | Promise<void>> },
  installButtonText: { type: String, default: "安装" },
});

const state = ref<ToolInstallState>("initial");
const downloading = ref(false);
const downloadPercent = ref(0);

async function handleInstall() {
  if (downloading.value) return;
  const localFile = props.savePath;
  const outputDir = path.dirname(localFile);
  const exists = await existsFile(localFile);
  if (exists) {
    message.info("文件已下载");
    await handleInstallLocal(localFile, outputDir);
    return;
  }

  downloading.value = true;
  downloadPercent.value = 0;
  await downloadAndUnzip({
    id: props.id,
    state,
    url: props.downloadUrl,
    savePath: localFile,
    progress: e => (downloadPercent.value = Math.floor(e.percent * 100)),
    downloadSuccess: () => {
      downloading.value = false;
      message.success("下载完成");
    },
    archiveOutput: outputDir,
    unzipComplete: e => props.afterUnzipComplete?.(e, props.completeArgs),
  });
}

async function handleInstallLocal(localFile: string, outputDir: string) {
  await installArchiveFile({
    id: props.id,
    state,
    archiveFile: localFile,
    outputDir,
    unzipComplete: e => props.afterUnzipComplete?.(e, props.completeArgs),
    deleteArchive: true,
  });
}
</script>

<template>
  <span v-if="isInstalled" class="color-gray ph-8">已安装</span>
  <template v-else>
    <a-button v-if="state === 'initial'" type="text" size="small" :icon="hc(DownloadOutlined)" @click.stop="handleInstall"
      >{{ installButtonText }}
    </a-button>
    <a-space v-else-if="state === 'downloading'">
      <span>正在下载</span>
      <span>{{ downloadPercent }}%</span>
      <LoadingOutlined />
    </a-space>
    <a-space v-else>
      <span v-if="state === 'unziping'">正在解压</span>
      <span v-if="state === 'installing'">正在安装</span>
      <LoadingOutlined />
    </a-space>
  </template>
</template>
